package com.qf.controller;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.netflix.discovery.converters.Auto;
import com.qf.aop.annocation.FormToken;
import com.qf.aop.annocation.LoginUser;
import com.qf.common.ResultEntity;
import com.qf.common.ShopConstatns;
import com.qf.entity.Car;
import com.qf.entity.Goods;
import com.qf.entity.User;
import com.qf.feign.api.GoodsService;
import com.qf.service.ICarService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

@RequestMapping("/carController")
@Controller
@Slf4j
public class CarController {

    @Autowired
    private ICarService carService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private GoodsService goodsService;

    @RequestMapping("/deleteCar/{gid}")
    @LoginUser
    @ResponseBody
    public ResultEntity deleteCar(User user,
                                  @PathVariable Integer gid,
                                  @CookieValue(name = ShopConstatns.SHOP_CAT_ANNO_NAME, required = false, defaultValue = "") String annoId) {
        if (user != null) {
            // 从数据库中删除
            carService.delete(new EntityWrapper<Car>().eq("uid", user.getId()).and().eq("gid", gid));
        } else {
            // 从redis中删除
            if (!StringUtils.isEmpty(annoId)) {
                stringRedisTemplate.opsForHash().delete(annoId, gid.toString());
            }
        }
        return ResultEntity.success();
    }

    @LoginUser // 表示这个方法需注入当前登录的用户对象
    @RequestMapping("/addCar")
    @ResponseBody
    public ResultEntity addCar(User user, @RequestBody Car car,
                               @CookieValue(name = ShopConstatns.SHOP_CAT_ANNO_NAME, required = false, defaultValue = "") String annoId,
                               HttpServletResponse response) {
        if (user == null) { // 没有登录保存到redis中
            // 判断用户是否已经有了匿名用户id
            if (StringUtils.isEmpty(annoId)) {
                // 给没有登录的用户也分配一个匿名id(未登录)
                annoId = UUID.randomUUID().toString();

                // 创建一个cookie用来保存匿名用户的id
                Cookie cookie = new Cookie(ShopConstatns.SHOP_CAT_ANNO_NAME, annoId);
                cookie.setMaxAge(60 * 60 * 24 * 7);
                cookie.setPath("/");// 解决跨域
                response.addCookie(cookie); // 设置到头部
            }

            String redisNum = stringRedisTemplate.opsForHash().get(annoId, car.getGid().toString()).toString();
            if (StringUtils.isEmpty(redisNum)) {
                // 把匿名用户的购物车保存到redis
                stringRedisTemplate.opsForHash().put(annoId, car.getGid().toString(), car.getSum().toString());
                // 给key设置过期时间
                stringRedisTemplate.expire(annoId, 7, TimeUnit.DAYS);
            } else {
                Integer newNum = Integer.parseInt(redisNum) + car.getSum();
                stringRedisTemplate.opsForHash().put(annoId, car.getGid().toString(),newNum.toString());
            }


        } else { // 已经登录保存到数据库

            // 给当前的购物车对象设置用户的ID
            car.setUid(user.getId());

            // 先判断是否商品是否存在
            Car dbCar = carService.selectOne(new EntityWrapper<Car>().eq("uid", user.getId()).and().eq("gid", car.getGid()));
            if (dbCar == null) {
                // 保存到数据库
                carService.insert(car);
            } else {
                dbCar.setSum(dbCar.getSum() + car.getSum()); // 数据的数量+新的数量
                carService.updateById(dbCar); // 跟新
            }
        }
//        return "userList.html";
        return ResultEntity.success();
    }

    // key field1 value1
    // key field2 value2
    // key field3 value3
    @RequestMapping("/getCarList")
    @LoginUser
    public String getCarList(User user,
                             @CookieValue(name = ShopConstatns.SHOP_CAT_ANNO_NAME, required = false, defaultValue = "") String annoId,
                             ModelMap modelMap) {

        List<Car> carList = null;
        if (user == null) {
            // 在没有登录的情况下，判断用户是否有匿名id
            if (!StringUtils.isEmpty(annoId)) {

                carList = new ArrayList<>(); // 实例化集合

                // 1.先根据key获取对应的fields
                Set<Object> fileds = stringRedisTemplate.opsForHash().keys(annoId);

                for (Object filed : fileds) {
                    // 2.在根据key和field查询value
                    String value = stringRedisTemplate.opsForHash().get(annoId, filed.toString()).toString();

                    // 3.封装操作
                    Car car = new Car();
                    car.setGid(Integer.parseInt(filed.toString()));
                    car.setSum(Integer.parseInt(value));

                    // 4.添加到集合
                    carList.add(car);
                }
            }
        } else {
            EntityWrapper wrapper = new EntityWrapper();
            wrapper.eq("uid", user.getId());
            carList = carService.selectList(wrapper);
        }

        getCarInfoList(carList);

        log.debug("carList {}", carList);

        modelMap.put("carList", carList);

        return "carList";
    }

    public void getCarInfoList(List<Car> carList){

        if (carList != null && !carList.isEmpty()) {
            // 遍历购物车集合取出gid
            List<Integer> gidList = new ArrayList<>();
            for (Car car : carList) {
                gidList.add(car.getGid()); // 商品id
            }

            // 1.先查询购物车中商品的信息
            Map<Integer, Goods> goodsMap = goodsService.getGoodsMap(gidList);

            // 2.把商品信息放入到对应的购车中
            // 遍历购物车，查询商品信息
            for (Car car : carList) {

                // 设置商品信息
                Goods goods = goodsMap.get(car.getGid());
                car.setGoods(goods);

                // 商品价格*商品的数量
                BigDecimal gprice = goods.getGprice();
                BigDecimal multiply = gprice.multiply(BigDecimal.valueOf(car.getSum()));
                car.setSubTotal(multiply);
            }
        }

    }

    // 从reids中把数据同步到MySQL
    @RequestMapping("/mergeCar")
    @ResponseBody
    public void mergeCar(String annoId, Integer uid) {

        List<Car> carList = new ArrayList<>();

        // 1.先根据key获取对应的fields
        Set<Object> fileds = stringRedisTemplate.opsForHash().keys(annoId);

        for (Object filed : fileds) {
            // 2.在根据key和field查询value
            String value = stringRedisTemplate.opsForHash().get(annoId, filed.toString()).toString();

            // 3.封装操作
            Car car = new Car();
            car.setGid(Integer.parseInt(filed.toString()));
            car.setSum(Integer.parseInt(value));
            car.setUid(uid);

            carList.add(car);
        }

        if (!carList.isEmpty()) {

            // 把缓存中的购物车情况
            stringRedisTemplate.delete(annoId);

            // 同步的MySQL中
            carService.insertBatch(carList);
        }
    }

    @RequestMapping("/getUserCarCount")
    @LoginUser
    @ResponseBody
    public ResultEntity getUserCarCount(
            User user,
            @CookieValue(name = ShopConstatns.SHOP_CAT_ANNO_NAME, required = false, defaultValue = "") String annoId) {
        Integer count = 0;
        if (user == null) {
            if (!StringUtils.isEmpty(annoId)) {
                count = stringRedisTemplate.opsForHash().keys(annoId).size();
            }
        } else {
            EntityWrapper wrapper = new EntityWrapper();
            wrapper.eq("uid", user.getId());
            count = carService.selectCount(wrapper);
        }
        return ResultEntity.success(count);
    }

    @RequestMapping("/getCarListByUid/{id}")
    @ResponseBody
    public List<Car> getCarListByUid(@PathVariable("id") Integer id){
        List<Car> cars = carService.selectList(new EntityWrapper<Car>().eq("uid", id));
        getCarInfoList(cars);
        return cars;
    }
}
